﻿/*
 * RegExpress
 * 
 * Copyright (c) 2010, Daniel McGaughran
 * 
 * Licensed under the Apache Licence, Version 2.0 (the "Licence");
 * you may not use this file except in compliance with the Licence.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Licence is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and
 * limitations under the Licence.
 * 
 */

using System;
using System.Collections.Generic;
using System.Xml;
using RegExpressModel.Entities;
using RegExpressModel.Utility;


namespace RegExpressModel
{
	class SlideLoader
	{
		private static Dictionary<string, Func<string, string, XmlNode, Slide>> _generator;

		static SlideLoader()
		{
			_generator = new Dictionary<string, Func<string, string, XmlNode, Slide>>();
			_generator.Add(SlideType.Title.ToString(), CreateTitleSlide);
			_generator.Add(SlideType.NavMap.ToString(), CreateNullObject);
			_generator.Add(SlideType.Image.ToString(), CreateImageSlide);
			_generator.Add(SlideType.FixedContent.ToString(), CreateFixedContentSlide);
			_generator.Add(SlideType.SourceCode.ToString(), CreateSourceCodeSlide);
			_generator.Add(SlideType.BasicMatch.ToString(), CreateBasicMatchSlide);
			_generator.Add(SlideType.MultiMatch.ToString(), CreateMultiMatchSlide);
			_generator.Add(SlideType.FindMatches.ToString(), CreateFindMatchesSlide);
			_generator.Add(SlideType.ReplaceMatches.ToString(), CreateReplaceMatchesSlide);
		}



		public bool LoadSlideDataFromFile(string filename)
		{
			XmlDocument slideDataDoc = new XmlDocument();

			try
			{
				slideDataDoc.Load(filename);
			}
			catch (Exception)
			{
				//Invalid filename, insufficient permissions, file not found
				return false;
			}

			XmlNodeList slideNodes = slideDataDoc.SelectNodes(Constants.SlideXPath);
			if (slideNodes == null) return false;

			foreach(XmlNode node in slideNodes)
			{
				LoadSlide(node);
			}
			return true;
		}



		public Func<Slide, bool> AddSlide { get; set; }


		private void LoadSlide(XmlNode slideXml)
		{
			string id = slideXml.GetTextAttribute("ID");
			string slideType = slideXml.GetTextAttribute("Type");
			string templateName = slideXml.GetTextAttribute("Template");

			Slide newSlide = _generator[slideType](id, templateName, slideXml);
			if (newSlide == null) return;

			newSlide.Title = slideXml.GetTextValue("Title");

			XmlNode navNode = slideXml.SelectSingleNode("Navigation");
			if (navNode != null)
			{
				newSlide.NextID = navNode.GetTextAttribute("NextID");
				newSlide.PrevID = navNode.GetTextAttribute("PrevID");
			}

			if (AddSlide != null)
				AddSlide(newSlide);
		}


		private static Slide CreateTitleSlide(string id, string templateName, XmlNode slideXml)
		{
			TitleSlide slide = new TitleSlide(id, templateName)
			{
				SubTitle = slideXml.GetTextValue("SubTitle")
			};
			return slide;
		}

		private static Slide CreateImageSlide(string id, string templateName, XmlNode slideXml)
		{
			ImageSlide slide = new ImageSlide(id, templateName)
			{
				ImageUri = slideXml.GetTextValue("ImageUri"),
				Caption = slideXml.GetTextValue("Caption")
			};
			return slide;
		}

		private static Slide CreateSourceCodeSlide(string id, string templateName, XmlNode slideXml)
		{
			SourceCodeSlide slide = new SourceCodeSlide(id, templateName)
			{
				SourceCode = slideXml.GetTextValue("SourceCode"),
				Caption = slideXml.GetTextValue("Caption")
			};
			return slide;
		}

		private static Slide CreateFixedContentSlide(string id, string templateName, XmlNode slideXml)
		{
			FixedContentSlide slide = new FixedContentSlide(id, templateName);
			return slide;
		}

		private static Slide CreateBasicMatchSlide(string id, string templateName, XmlNode slideXml)
		{
			BasicMatchSlide slide = new BasicMatchSlide(id, templateName)
			{
				Caption = slideXml.GetTextValue("Caption"),
			};

			XmlNode matchModelNode = slideXml.SelectSingleNode("MatchModel");
			XmlNode matchOptionsNode = slideXml.SelectSingleNode("MatchModel/Options");
			if (matchModelNode != null)
			{
				BasicMatchModel matchModel = slide.MatchModel;
				matchModel.RegExpression = matchModelNode.GetTextValue("RegExpression");
				matchModel.Input = matchModelNode.GetTextValue("Input");

				if(matchOptionsNode != null)
				{
					if (matchOptionsNode.GetIntAttribute("IsCaseIgnored") != 0)
						matchModel.IsCaseIgnored = true;
					if (matchOptionsNode.GetIntAttribute("IsMultiLine") != 0)
						matchModel.IsMultiLine = true;
					if (matchOptionsNode.GetIntAttribute("IsNewlineMatchedByDot") != 0)
						matchModel.IsNewlineMatchedByDot = true;
					if (matchOptionsNode.GetIntAttribute("IsWhitespaceIgnored") != 0)
						matchModel.IsWhitespaceIgnored = true;
				}
			}

			return slide;
		}

		private static Slide CreateMultiMatchSlide(string id, string templateName, XmlNode slideXml)
		{
			MultiMatchSlide slide = new MultiMatchSlide(id, templateName)
			{
				Caption = slideXml.GetTextValue("Caption")
			};

			XmlNode matchModelNode = slideXml.SelectSingleNode("MatchModel");
			XmlNode matchOptionsNode = slideXml.SelectSingleNode("MatchModel/Options");
			if (matchModelNode != null)
			{
				MultiMatchModel matchModel = slide.MatchModel;
				matchModel.RegExpression = matchModelNode.GetTextValue("RegExpression");
				XmlNodeList inputNodes = matchModelNode.SelectNodes("MatchCases/MatchCase");
				
				if(inputNodes != null)
				{
					foreach(XmlNode currentInput in inputNodes)
					{
						matchModel.AddMatchCase(currentInput.InnerXml);
					}
				}

				if (matchOptionsNode != null)
				{
					if (matchOptionsNode.GetIntAttribute("IsCaseIgnored") != 0)
						matchModel.IsCaseIgnored = true;
					if (matchOptionsNode.GetIntAttribute("IsMultiLine") != 0)
						matchModel.IsMultiLine = true;
					if (matchOptionsNode.GetIntAttribute("IsNewlineMatchedByDot") != 0)
						matchModel.IsNewlineMatchedByDot = true;
					if (matchOptionsNode.GetIntAttribute("IsWhitespaceIgnored") != 0)
						matchModel.IsWhitespaceIgnored = true;
				}
			}
			return slide;
		}

		private static Slide CreateFindMatchesSlide(string id, string templateName, XmlNode slideXml)
		{
			FindMatchesSlide slide = new FindMatchesSlide(id, templateName)
			{
				Caption = slideXml.GetTextValue("Caption")
			};

			XmlNode matchModelNode = slideXml.SelectSingleNode("MatchModel");
			XmlNode matchOptionsNode = slideXml.SelectSingleNode("MatchModel/Options");
			if (matchModelNode != null)
			{
				FindMatchesModel matchModel = slide.MatchModel;
				matchModel.RegExpression = matchModelNode.GetTextValue("RegExpression");
				matchModel.Input = matchModelNode.GetTextValue("Input");

				if (matchOptionsNode != null)
				{
					if (matchOptionsNode.GetIntAttribute("IsCaseIgnored") != 0)
						matchModel.IsCaseIgnored = true;
					if (matchOptionsNode.GetIntAttribute("IsMultiLine") != 0)
						matchModel.IsMultiLine = true;
					if (matchOptionsNode.GetIntAttribute("IsNewlineMatchedByDot") != 0)
						matchModel.IsNewlineMatchedByDot = true;
					if (matchOptionsNode.GetIntAttribute("IsWhitespaceIgnored") != 0)
						matchModel.IsWhitespaceIgnored = true;
				}
			}
			return slide;
		}

		private static Slide CreateReplaceMatchesSlide(string id, string templateName, XmlNode slideXml)
		{
			ReplaceMatchesSlide slide = new ReplaceMatchesSlide(id, templateName)
			{
				Caption = slideXml.GetTextValue("Caption")
			};

			XmlNode matchModelNode = slideXml.SelectSingleNode("MatchModel");
			XmlNode matchOptionsNode = slideXml.SelectSingleNode("MatchModel/Options");
			if (matchModelNode != null)
			{
				ReplaceMatchesModel matchModel = slide.MatchModel;
				matchModel.RegExpression = matchModelNode.GetTextValue("RegExpression");
				matchModel.Input = matchModelNode.GetTextValue("Input");
				matchModel.ReplacementExpression = matchModelNode.GetTextValue("ReplacementExpression");

				if (matchOptionsNode != null)
				{
					if (matchOptionsNode.GetIntAttribute("IsCaseIgnored") != 0)
						matchModel.IsCaseIgnored = true;
					if (matchOptionsNode.GetIntAttribute("IsMultiLine") != 0)
						matchModel.IsMultiLine = true;
					if (matchOptionsNode.GetIntAttribute("IsNewlineMatchedByDot") != 0)
						matchModel.IsNewlineMatchedByDot = true;
					if (matchOptionsNode.GetIntAttribute("IsWhitespaceIgnored") != 0)
						matchModel.IsWhitespaceIgnored = true;
				}
			}
			return slide;
		}


		private static Slide CreateNullObject(string id, string templateName, XmlNode slideXml)
		{
			return null;
		}



	}
}
